package com.jemaa.news.utils;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.derby.impl.io.VFMemoryStorageFactory;
import org.apache.derby.jdbc.EmbeddedDriver;
import org.springframework.jdbc.datasource.embedded.ConnectionProperties;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseConfigurer;
import org.springframework.jdbc.datasource.embedded.OutputStreamFactory;

public class JemaaDerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigurer {

	
	private static final Log logger = LogFactory.getLog(JemaaDerbyEmbeddedDatabaseConfigurer.class);
	
	private static final String URL_TEMPLATE = "jdbc:derby:%s";

	// Error code that indicates successful shutdown
	private static final String SHUTDOWN_CODE = "08006";

	private static JemaaDerbyEmbeddedDatabaseConfigurer INSTANCE;

	/**
	 * Get the singleton {@link JemaaDerbyEmbeddedDatabaseConfigurer} instance.
	 * @return the configurer
	 * @throws ClassNotFoundException if Derby is not on the classpath
	 */
	public static synchronized JemaaDerbyEmbeddedDatabaseConfigurer getInstance() throws ClassNotFoundException {
		if (INSTANCE == null) {
			// disable log file
			System.setProperty("derby.stream.error.method",
					OutputStreamFactory.class.getName() + ".getNoopOutputStream");
			INSTANCE = new JemaaDerbyEmbeddedDatabaseConfigurer();
		}
		return INSTANCE;
	}

	private JemaaDerbyEmbeddedDatabaseConfigurer() {
	}

	public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
		properties.setDriverClass(EmbeddedDriver.class);
		properties.setUrl(String.format(URL_TEMPLATE, databaseName, "create=true"));
		properties.setUsername("");
		properties.setPassword("");
	}

	public void shutdown(DataSource dataSource, String databaseName) {
		try {
			new EmbeddedDriver().connect(
					String.format(URL_TEMPLATE, databaseName, "shutdown=true"), new Properties());
		}
		catch (SQLException ex) {
			if (SHUTDOWN_CODE.equals(ex.getSQLState())) {
				purgeDatabase(databaseName);
			}
			else {
				logger.warn("Could not shutdown in-memory Derby database", ex);
			}
		}
	}

	/**
	 * Purge the in-memory database, to prevent it from hanging around after
	 * being shut down.
	 */
	private void purgeDatabase(String databaseName) {
		// TODO: update this code once Derby adds a proper way to remove an in-memory db
		// (see http://wiki.apache.org/db-derby/InMemoryBackEndPrimer for details)
		try {
			VFMemoryStorageFactory.purgeDatabase(new File(databaseName).getCanonicalPath());
		}
		catch (IOException ex) {
			logger.warn("Could not purge in-memory Derby database", ex);
		}
	}
	
	

}
